"""模拟测试服务"""
from typing import Dict, Any, List, Optional
from datetime import datetime
import uuid
import json
import re
from app.ai.question_generator import question_generator
from app.db.question_bank import get_question_by_id, SUBJECT_WEIGHTS
from app.ai.evaluation_engine import get_evaluation_engine


class MockExamService:
    """模拟测试服务"""
    
    # 模拟测试配置
    EXAM_CONFIGS = {
        "quick": {
            "name": "快速评估",
            "question_count": 20,  # 20题，约15-20分钟
            "time_limit": 1200,  # 20分钟
            "include_comprehensive": True
        },
        "standard": {
            "name": "标准评估",
            "question_count": 50,  # 50题，约40-50分钟
            "time_limit": 3000,  # 50分钟
            "include_comprehensive": True
        },
        "full": {
            "name": "完整模拟",
            "question_count": 100,  # 100题，约90分钟
            "time_limit": 5400,  # 90分钟
            "include_comprehensive": True
        }
    }
    
    # 知识阶段定义
    KNOWLEDGE_STAGES = {
        "beginner": {
            "name": "入门阶段",
            "score_range": (0, 50),
            "description": "刚开始学习法律，基础知识较为薄弱",
            "advice": "建议从基础理论开始，系统学习各科目的核心概念",
            "icon": "🌱"
        },
        "foundation": {
            "name": "基础阶段",
            "score_range": (50, 65),
            "description": "已掌握基础知识，但理解和应用能力有待提升",
            "advice": "加强案例分析训练，提高法律思维和推理能力",
            "icon": "📚"
        },
        "intermediate": {
            "name": "进阶阶段",
            "score_range": (65, 75),
            "description": "具备一定的法律基础，能够处理常规法律问题",
            "advice": "重点突破薄弱环节，加强综合题训练，提高解题技巧",
            "icon": "📖"
        },
        "advanced": {
            "name": "高级阶段",
            "score_range": (75, 85),
            "description": "法律知识扎实，能够灵活运用法律知识解决问题",
            "advice": "保持训练强度，重点练习综合题和难题，查漏补缺",
            "icon": "🎯"
        },
        "expert": {
            "name": "专家阶段",
            "score_range": (85, 100),
            "description": "法律知识全面，具备较强的法律思维和解题能力",
            "advice": "继续保持，可以尝试更高难度的题目，准备冲刺高分",
            "icon": "🏆"
        }
    }
    
    async def create_mock_exam(
        self,
        user_id: str,
        exam_type: str = "quick"
    ) -> Dict[str, Any]:
        """
        创建模拟测试
        
        Args:
            user_id: 用户ID
            exam_type: 测试类型（quick/standard/full）
            
        Returns:
            模拟测试信息
        """
        if exam_type not in self.EXAM_CONFIGS:
            exam_type = "quick"
        
        config = self.EXAM_CONFIGS[exam_type]
        exam_id = f"exam_{uuid.uuid4().hex[:8]}"
        
        # 生成题目（包含综合题）
        question_ids = await self._generate_exam_questions(
            config["question_count"],
            include_comprehensive=config.get("include_comprehensive", True)
        )
        
        return {
            "exam_id": exam_id,
            "user_id": user_id,
            "exam_type": exam_type,
            "name": config["name"],
            "question_count": len(question_ids),
            "time_limit": config["time_limit"],
            "question_ids": question_ids,
            "started_at": datetime.now().isoformat(),
            "status": "created"
        }
    
    async def _generate_exam_questions(
        self,
        count: int,
        include_comprehensive: bool = True
    ) -> List[str]:
        """生成测试题目"""
        # 计算各科目题目数量（基于权重）
        subject_distribution = {
            "civil_law": 0.18,
            "civil_procedure": 0.12,
            "criminal_law": 0.15,
            "criminal_procedure": 0.10,
            "administrative": 0.12,
            "commercial": 0.15,
            "international": 0.08,
            "comprehensive": 0.10 if include_comprehensive else 0
        }
        
        # 使用题目生成器推荐
        question_ids = await question_generator.recommend_questions(
            user_id="exam_user",
            count=count,
            subject_distribution=subject_distribution
        )
        
        return question_ids
    
    async def submit_exam(
        self,
        exam_id: str,
        user_id: str,
        answers: Dict[str, str],  # {question_id: answer}
        time_spent: int  # 秒
    ) -> Dict[str, Any]:
        """
        提交模拟测试并评估
        
        Args:
            exam_id: 测试ID
            user_id: 用户ID
            answers: 答案字典
            time_spent: 用时（秒）
            
        Returns:
            测试结果和知识阶段评估
        """
        # 格式化正确答案用于显示（将JSON格式转换为可读文本）
        def format_answer_for_display(answer_text: str) -> str:
            """将答案格式化为可读文本"""
            if not answer_text:
                return ""
            
            # 尝试解析JSON格式
            try:
                if answer_text.strip().startswith('['):
                    data = json.loads(answer_text)
                    if isinstance(data, list):
                        # 提取所有选项ID并排序
                        option_ids = []
                        for item in data:
                            if isinstance(item, dict):
                                option_id = item.get("id", "")
                                if option_id:
                                    option_ids.append(option_id)
                        if option_ids:
                            # 按字母顺序排序，然后用"、"连接
                            option_ids.sort()
                            return "、".join([f"选项{id}" for id in option_ids])
            except:
                pass
            
            # 如果不是JSON格式，直接返回原文本
            return answer_text
        
        # 评估答案
        results = []
        correct_count = 0
        subject_scores = {}  # 各科目得分
        
        for question_id, user_answer in answers.items():
            question_data = get_question_by_id(question_id)
            if not question_data:
                continue
            
            correct_answer = question_data.get("correct_answer", "")
            question_type = question_data.get("type", "single_choice")
            
            # 提取选项标识（支持单选和多选）
            
            def extract_options(answer_text: str) -> set:
                """从答案文本中提取所有选项标识"""
                if not answer_text:
                    return set()
                
                options = set()
                
                # 尝试解析JSON格式（如：[{"id":"A","text":"..."},{"id":"C","text":"..."}]）
                try:
                    if answer_text.strip().startswith('['):
                        data = json.loads(answer_text)
                        if isinstance(data, list):
                            for item in data:
                                if isinstance(item, dict):
                                    option_id = item.get("id", "")
                                    if option_id:
                                        options.add(f"选项{option_id}")
                except:
                    pass
                
                # 提取"选项X"格式的所有选项（支持"选项A、选项C"格式）
                matches = re.findall(r'选项([A-D])', answer_text)
                for match in matches:
                    options.add(f"选项{match}")
                
                return options
            
            # 判断是单选还是多选
            # 先检查正确答案格式，如果正确答案包含多个选项，自动按多选题处理
            correct_options_set = extract_options(correct_answer)
            has_multiple_correct_answers = len(correct_options_set) > 1
            
            # 如果正确答案有多个选项，但题目类型是单选，自动修正为多选题
            if has_multiple_correct_answers and question_type == "single_choice":
                print(f"⚠️ 题目 {question_id} 类型标记为单选，但正确答案包含多个选项，自动按多选题处理")
                is_multiple_choice = True
            else:
                is_multiple_choice = question_type in ["multiple_choice", "indefinite_choice"]
            
            # 答案判断结果
            is_correct = False
            is_partially_correct = False
            missing_options = []  # 缺少的选项
            extra_options = []  # 多余的选项
            
            if is_multiple_choice:
                # 多选题：比较选项集合
                user_options = extract_options(user_answer)
                correct_options = extract_options(correct_answer)
                
                if len(user_options) == 0:
                    # 未选择任何选项
                    is_correct = False
                    missing_options = list(correct_options)
                elif user_options == correct_options:
                    # 完全正确
                    is_correct = True
                elif user_options.issubset(correct_options):
                    # 部分正确：用户选择的都在正确答案内，但不全
                    is_partially_correct = True
                    is_correct = False
                    missing_options = list(correct_options - user_options)
                else:
                    # 有错误选项：用户选择了不在正确答案中的选项
                    is_correct = False
                    missing_options = list(correct_options - user_options)
                    extra_options = list(user_options - correct_options)
            else:
                # 单选题：只比较第一个选项
                # 先从正确答案中提取选项（支持JSON格式和简单格式）
                correct_options_set = extract_options(correct_answer)
                user_options_set = extract_options(user_answer)
                
                # 单选题应该只有一个正确选项
                if len(correct_options_set) == 1 and len(user_options_set) == 1:
                    # 比较选项集合
                    is_correct = user_options_set == correct_options_set
                    if not is_correct:
                        # 提取正确选项的ID（去掉"选项"前缀）
                        correct_option_id = list(correct_options_set)[0].replace("选项", "")
                        missing_options = [f"选项{correct_option_id}"]
                else:
                    # 兼容旧逻辑：使用正则表达式提取
                    user_option = re.search(r'选项([A-D])', user_answer) if user_answer else None
                    correct_option = re.search(r'选项([A-D])', correct_answer) if correct_answer else None
                    is_correct = (
                        user_option and correct_option and 
                        user_option.group(1) == correct_option.group(1)
                    )
                    if not is_correct and correct_option:
                        missing_options = [f"选项{correct_option.group(1)}"]
            
            if is_correct:
                correct_count += 1
            
            # 处理部分正确的情况
            partial_correct_feedback = None
            unmastered_knowledge_points = []
            
            if is_partially_correct:
                # 分析缺少选项对应的知识点
                all_knowledge_points = question_data.get("knowledge_points", [])
                if missing_options and all_knowledge_points:
                    # 计算缺少的比例
                    missing_ratio = len(missing_options) / len(correct_options) if correct_options else 0
                    # 标记相应比例的知识点为未掌握
                    num_missing_kp = max(1, int(len(all_knowledge_points) * missing_ratio))
                    unmastered_knowledge_points = all_knowledge_points[:num_missing_kp]
                elif missing_options:
                    unmastered_knowledge_points = [f"选项{opt.replace('选项', '')}相关知识点" for opt in missing_options]
                
                # 生成部分正确的批注
                missing_options_text = "、".join([opt.replace("选项", "选项") for opt in missing_options])
                partial_correct_feedback = {
                    "is_partial": True,
                    "message": f"您的答案部分正确，但缺少了 {missing_options_text}。",
                    "missing_options": missing_options,
                    "missing_knowledge_points": unmastered_knowledge_points,
                    "feedback": f"您已掌握了部分知识点，但还需要加强对以下知识点的理解：{', '.join(unmastered_knowledge_points) if unmastered_knowledge_points else '相关知识点'}。"
                }
            elif not is_correct:
                # 完全错误时，标记所有知识点为未掌握
                unmastered_knowledge_points = question_data.get("knowledge_points", [])
            
            # 统计各科目得分
            subject = question_data.get("subject", "unknown")
            if subject not in subject_scores:
                subject_scores[subject] = {"total": 0, "correct": 0}
            subject_scores[subject]["total"] += 1
            if is_correct:
                subject_scores[subject]["correct"] += 1
            
            formatted_correct_answer = format_answer_for_display(correct_answer)
            
            # 详细的分析（使用大模型生成）
            # 优化：只对错误题目进行详细分析，减少处理时间
            # 答对时：使用基础解释，不调用大模型（节省时间）
            # 答错时：分析错误原因，指出问题
            detailed_analysis = None
            
            # 答对时，使用基础解释，不调用大模型（优化性能）
            if is_correct and question_data:
                # 使用基础解释，不调用大模型以节省时间
                detailed_analysis = {
                    "detailed_analysis": question_data.get("explanation", "答案正确。"),
                    "thinking_approach": "您的答案是正确的。",
                    "correct_answer_explanation": question_data.get("explanation", ""),
                    "knowledge_points": question_data.get("knowledge_points", []),
                    "reinforcement_suggestions": []
                }
            
            # 详细的错误分析（使用大模型生成，包括做题思路、正确答案解释、错误点分析）
            # 只对错误题目进行详细分析，减少超时时间
            detailed_error_analysis = None
            if not is_correct or is_partially_correct:
                # 使用评估引擎分析错误
                try:
                    import asyncio
                    evaluation_engine = get_evaluation_engine()
                    # 生成详细的错误分析（减少超时时间，优化性能）
                    detailed_error_analysis = await asyncio.wait_for(
                        evaluation_engine.generate_detailed_error_analysis(
                            question_content=question_data.get("content", ""),
                            question_options=question_data.get("options", []),
                            user_answer=user_answer,
                            correct_answer=correct_answer,
                            explanation=question_data.get("explanation", ""),
                            knowledge_points=question_data.get("knowledge_points", [])
                        ),
                        timeout=10.0  # 减少到10秒超时，避免整体请求超时
                    )
                except asyncio.TimeoutError:
                    print(f"生成详细错误分析超时（10秒），使用基础分析 - 题目 {question_id}")
                    # 使用基础错误分析
                    detailed_error_analysis = {
                        "error_analysis": question_data.get("explanation", "答案错误，请查看解析。"),
                        "thinking_approach": "请仔细分析题目条件和选项。",
                        "correct_answer_explanation": question_data.get("explanation", ""),
                        "error_points": ["请查看标准解析"],
                        "knowledge_points": question_data.get("knowledge_points", [])
                    }
                except Exception as e:
                    print(f"生成详细错误分析失败: {e}")
                    # 使用基础错误分析
                    detailed_error_analysis = {
                        "error_analysis": question_data.get("explanation", "答案错误，请查看解析。"),
                        "thinking_approach": "请仔细分析题目条件和选项。",
                        "correct_answer_explanation": question_data.get("explanation", ""),
                        "error_points": ["请查看标准解析"],
                        "knowledge_points": question_data.get("knowledge_points", [])
                    }
            
            results.append({
                "question_id": question_id,
                "user_answer": user_answer,
                "correct_answer": formatted_correct_answer,
                "is_correct": is_correct,
                "is_partially_correct": is_partially_correct,  # 部分正确标识
                "partial_correct_feedback": partial_correct_feedback,  # 部分正确的批注
                "unmastered_knowledge_points": unmastered_knowledge_points,  # 未掌握的知识点
                "missing_options": missing_options,  # 缺少的选项
                "extra_options": extra_options,  # 多余的选项
                "detailed_error_analysis": detailed_error_analysis,  # 详细的错误分析（大模型生成）
                "detailed_analysis": detailed_analysis if is_correct else detailed_error_analysis,  # 详细分析（答对时：为什么正确；答错时：错误分析）
                "subject": question_data.get("category"),
                "knowledge_points": question_data.get("knowledge_points", [])
            })
        
        # 计算总分
        total_questions = len(results)
        accuracy = (correct_count / total_questions * 100) if total_questions > 0 else 0
        
        # 计算各科目准确率
        subject_accuracy = {}
        for subject, scores in subject_scores.items():
            if scores["total"] > 0:
                subject_accuracy[subject] = scores["correct"] / scores["total"] * 100
        
        # 评估知识阶段
        stage_assessment = self._assess_knowledge_stage(accuracy, subject_accuracy)
        
        return {
            "exam_id": exam_id,
            "user_id": user_id,
            "total_questions": total_questions,
            "correct_count": correct_count,
            "accuracy": round(accuracy, 2),
            "time_spent": time_spent,
            "submitted_at": datetime.now().isoformat(),
            "subject_scores": subject_accuracy,
            "knowledge_stage": stage_assessment,
            "detailed_results": results,
            "recommendations": self._generate_recommendations(subject_accuracy, results)
        }
    
    def _assess_knowledge_stage(
        self,
        overall_accuracy: float,
        subject_accuracy: Dict[str, float]
    ) -> Dict[str, Any]:
        """评估法律知识阶段"""
        # 根据总分确定主要阶段
        main_stage = None
        for stage_key, stage_info in self.KNOWLEDGE_STAGES.items():
            min_score, max_score = stage_info["score_range"]
            if min_score <= overall_accuracy < max_score:
                main_stage = {
                    "key": stage_key,
                    **stage_info
                }
                break
        
        if not main_stage:
            # 如果超出范围，使用最高或最低阶段
            if overall_accuracy >= 85:
                main_stage = {
                    "key": "expert",
                    **self.KNOWLEDGE_STAGES["expert"]
                }
            else:
                main_stage = {
                    "key": "beginner",
                    **self.KNOWLEDGE_STAGES["beginner"]
                }
        
        # 分析各科目表现
        strong_subjects = []
        weak_subjects = []
        
        for subject, accuracy in subject_accuracy.items():
            if accuracy >= 75:
                strong_subjects.append({
                    "subject": subject,
                    "accuracy": accuracy
                })
            elif accuracy < 60:
                weak_subjects.append({
                    "subject": subject,
                    "accuracy": accuracy
                })
        
        return {
            "main_stage": main_stage,
            "overall_score": overall_accuracy,
            "strong_subjects": strong_subjects,
            "weak_subjects": weak_subjects,
            "assessment_date": datetime.now().isoformat()
        }
    
    def _generate_recommendations(
        self,
        subject_accuracy: Dict[str, float],
        results: List[Dict[str, Any]]
    ) -> List[str]:
        """生成学习建议"""
        recommendations = []
        
        # 基于薄弱科目
        weak_subjects = [
            subject for subject, accuracy in subject_accuracy.items()
            if accuracy < 60
        ]
        
        if weak_subjects:
            recommendations.append(
                f"建议重点加强以下科目的学习：{', '.join(weak_subjects)}"
            )
        
        # 基于错误类型分析（简化）
        error_knowledge_points = {}
        for result in results:
            if not result.get("is_correct"):
                for kp in result.get("knowledge_points", []):
                    error_knowledge_points[kp] = error_knowledge_points.get(kp, 0) + 1
        
        if error_knowledge_points:
            top_errors = sorted(
                error_knowledge_points.items(),
                key=lambda x: x[1],
                reverse=True
            )[:3]
            recommendations.append(
                f"建议重点复习以下知识点：{', '.join([kp[0] for kp in top_errors])}"
            )
        
        return recommendations


mock_exam_service = MockExamService()

